
#import "BCNSpcConstant.h"
#import <math.h>

//
//	Constant Array
//

static double[] A2s = {
            MAXFLOAT, MAXFLOAT, 1.880, 1.023, 0.729, 0.577, 0.483, 0.419, 0.373, 0.337, 0.308,
            0.285, 0.266, 0.249, 0.235, 0.23, 0.212, 0.203, 0.194, 0.187, 0.180,
            0.173, 0.167, 0.162, 0.157, 0.153};
            
static double[] Cns = {
            MAXFLOAT, MAXFLOAT,1.253, 1.128, 1.085, 1.064, 1.051, 1.042,1.036,1.032,
            1.028,1.025,1.023,1.021,1.019,1.018,1.017,1.016,1.015,1.014,1.013,1.013,
            1.012,1.011,1.011,1.011};

// D's for R-bar, appendix C of SPC_5e_Oakland
static double[] Dr001 = { 
            MAXFLOAT, MAXFLOAT, 4.12, 2.98, 2.57, 2.34, 2.21, 2.11, 2.04, 1.99, 1.93, 1.91, 1.87};
static double[] Dr025 = {
            MAXFLOAT, MAXFLOAT, 2.81, 2.17, 1.93, 1.81, 1.72, 1.66, 1.62, 1.58, 1.56, 1.53, 1.51};
static double[] Dr975 = { 
            MAXFLOAT, MAXFLOAT, 0.04, 0.18, 0.29, 0.37, 0.42, 0.46, 0.50, 0.52, 0.54, 0.56, 0.58};
static double[] Dr999 = {
            MAXFLOAT, MAXFLOAT, 0.00, 0.04, 0.10, 0.16, 0.21, 0.26, 0.29, 0.32, 0.35, 0.38, 0.40};
            
// B's for s-bar, appendix E of SPC_5e_Oakland
static double[] Bs001 = { 
           MAXFLOAT, MAXFLOAT, 4.12, 2.96, 2.52, 2.28, 2.13, 2.01, 1.93, 1.87, 1.81, 1.78, 1.73,
           1.69, 1.67, 1.64, 1.63, 1.61, 1.59, 1.57, 1.54, 1.52, 1.51, 1.50, 1.49, 1.48 };
static double[] Bs025 = { 
           MAXFLOAT, MAXFLOAT, 2.80, 2.17, 1.91, 1.78, 1.69, 1.61, 1.57, 1.53, 1.49, 1.49, 1.44, 
           1.42, 1.41, 1.40, 1.38, 1.36, 1.35, 1.34, 1.34, 1.33, 1.32, 1.31, 1.30, 1.30 };
static double[] Bs975 = {
           MAXFLOAT, MAXFLOAT, 0.04, 0.18, 0.29, 0.37, 0.43, 0.47, 0.51, 0.54, 0.56, 0.58, 0.60, 
           0.62, 0.63, 0.65, 0.66, 0.67, 0.68, 0.69, 0.69, 0.70, 0.71, 0.72, 0.72, 0.73  };
static double[] Bs999 = { 
           MAXFLOAT, MAXFLOAT, 0.02, 0.04, 0.10, 0.16, 0.22, 0.26, 0.30, 0.34, 0.37, 0.39, 0.42, 
           0.44, 0.46, 0.47, 0.49, 0.50, 0.52, 0.53, 0.54, 0.55, 0.56, 0.57, 0.58, 0.59  };
           
// C4, B3, B4 and A3                                                                                           
static double[] C4s = {                                                               
            MAXFLOAT, MAXFLOAT,  0.7979, 0.8862, 0.9213, 0.9400, 0.9515, 0.9594, 0.9650, 0.9693,           
            0.9727,0.9754, 0.9776,0.9794, 0.9810, 0.9823, 0.9835, 0.9845, 0.9854, 0.9862, 0.9869,              
            0.9876, 0.9882, 0.9887, 0.9892, 0.9896};
static double[] B3s = {                                                               
            MAXFLOAT, MAXFLOAT, 0, 0, 0, 0, 0.030, 0.118, 0.185, 0.239, 0.284, 0.321, 0.354, 0.382,        
            0.406, 0.428, 0.448, 0.466, 0.482, 0.497, 0.510, 0.523, 0.534, 0.545, 0.555, 0.565};
static double[] B4s = {                                                               
           MAXFLOAT, MAXFLOAT, 3.267, 2.568, 2.266, 2.089, 1.970, 1.882, 1.815, 1.761, 1.716, 1.679,       
           1.646, 1.618, 1.594, 1.572, 1.552, 1.534, 1.518, 1.503, 1.490, 1.477, 1.466, 1.455, 1.455, 1.435};
static double[] A3s = {                                                               
           MAXFLOAT, MAXFLOAT, 2.659, 1.954, 1.628, 1.427, 1.287, 1.182, 1.099, 1.032, 0.975, 0.927, 0.886,
           0.850, 0.817, 0.789, 0.763, 0.739, 0.718, 0.698, 0.680, 0.663, 0.647, 0.633, 0.619, 0.606};

                       
@implementation BCNSpcConstant
        

        +(double) GetDr001: (int) n
        {
            return n < 13 ? Dr001[n] : Dr001[13-1];
        }
        
        +(double) GetDr025: (int) n
        {
            return n < 13 ? Dr025[n] : Dr025[13 - 1];
        }
        
        +(double) GetDr975: (int) n
        {
            return n < 13 ? Dr975[n] : Dr975[13 - 1];
        }
        
        +(double) GetDr999: (int) n
        {
            return n < 13 ? Dr999[n] : Dr999[13 - 1];
        }
        
        +(double) GetBs001: (int) n
        {
            return n < 26 ? Bs001[n] : Bs001[26 - 1];
        }
        
        +(double) GetBs025: (int) n
        {
            return n < 26 ? Bs025[n] : Bs025[26 - 1];
        }
        
        +(double) GetBs975: (int) n
        {
            return n < 26 ? Bs975[n] : Bs975[26 - 1];
        }
        
        +(double) GetBs999:(int) n
        {
            return n < 26 ? Bs999[n] : Bs999[26 - 1];
        }
        
        +(double) GetA2s: (int) n
        {
            return n < 26 ? A2s[n] : A2s[26 - 1];
        }
        
        +(double) GetCns:(int) n
        {
            return n < 26 ? Cns[n] : Cns[26 - 1];
        }
        
        +(double) GetC4s: (int) n
        {
            if (n <= 25)
                return C4s[n];
            else
                return (double)(4 * (n - 1) / (double)(4 * n - 3));
        }
        
        +(double) GetA3s: (int) n
        {
            if (n <= 25)
                return A3s[n];
            else
            {
                double c4 = GetC4s(n);
                return 3.0 / c4 / sqrt((double)n);
            }
        }
        
        +(double) GetB3s:(int) n
        {
            if (n <= 25)
                return B3s[n];
            else
            {
                double c4 = GetC4s(n);
                return 1 - 3.0 / c4 / sqrt((double)2 * (n - 1));
            }
        }
        
        +(double) GetB4s:(int) n
        {
            if (n <= 25)
                return B4s[n];
            else
            {
                double c4 = GetC4s(n);
                return 1 + 3.0 / c4 / sqrt((double)2 * (n - 1));
            }
        }
        
@end // BCNSpcConstant


/*
*	use MAXFLOAT to instead of double.NaN in c# 
* or we can #define a macro for double.NaN to MAXFLOAT
*
*/
